package cz.czu.pef.DataModelling;

import java.util.*;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.persistence.*;

import org.hibernate.annotations.Index;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cz.czu.pef.DataModelling.utils.Lazy;

@Entity
@Table(name="PEOPLE")
@NamedQueries({
	@NamedQuery(name="findPersonByName", query="SELECT p FROM Person p WHERE p.firstName = :firstName AND p.lastName = :lastName")
})
@ManagedBean(name="person")
@ViewScoped
@Component
public class Person extends IdPersistenceObject
{
	private static final long serialVersionUID = -3846628860514746169L;

	@Column(name="BIRTH_DATE", nullable=true)
	@Index(name="IDX_PERSON_BIRTHDATE")
	private Date birthDate;

	@Column(name="FIRST_NAME", nullable=false, length=200)
	@Index(name="IDX_PERSON_FN")
	private String firstName;

	@Column(name="LAST_NAME", nullable=false, length=200)
	@Index(name="IDX_PERSON_LN")
	private String lastName;

	@ManyToOne(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},optional=true)
	private Address address;

	@OneToMany(fetch=FetchType.LAZY, targetEntity=Machinery.class, mappedBy="personOwner") // no cascade!
	private Set<Machinery> machineries;

	@OneToMany(fetch=FetchType.EAGER, targetEntity=Employee.class, mappedBy="person") // no cascade!
	private Set<Employee> employees;

	public Person()
	{
	}

	public Person(final String fn, final String ln)
	{
		setFirstName(fn);
		setLastName(ln);
	}

	public Person(final String fn, final String ln, Address address)
	{
		setFirstName(fn);
		setLastName(ln);
		setAddress(address);
	}

	public Address getAddress()
	{
		return address;
	}

	public String getFirstName()
	{
		return firstName;
	}


	public String getLastName()
	{
		return lastName;
	}

	public void setAddress(Address address)
	{
		this.address = address;
	}

	public void setFirstName(final String firstName)
	{
		this.firstName = firstName;
	}

	public void setLastName(final String lastName)
	{
		this.lastName = lastName;
	}

	
	public Date getBirthDate()
	{
		return birthDate;
	}

	
	public void setBirthDate(Date birthDate)
	{
		this.birthDate = birthDate;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public Set<Employee> getEmployees()
	{
		return employees;
	}

	
	public void setEmployees(Set<Employee> employees)
	{
		this.employees = employees;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	@Override
	public String toString()
	{
		return "Person [birthDate=" + birthDate + ", firstName=" + firstName + ", lastName=" + lastName + ", address=" + address + "]";
	}
	
	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public Set<Machinery> getMachineries()
	{
		return machineries;
	}

	/**
	 * Can be deleted after no machinery is owner directly by this person && person is not employee (external_worker).
	 */
	@Override
	public boolean canBeRemoved()
	{
		return (getMachineries().size() == 0) && getEmployees().size() == 0;
	}

}